using System;
using System.Collections.Generic;
using Holoville.HOTween;
using UnityEngine;

[RequireComponent(typeof(tk2dUIItem))]
[RequireComponent(typeof(BoxCollider))]
[RequireComponent(typeof(tk2dUIScrollableArea))]
public class tk2dUIScrollPage : MonoBehaviour
{
	public int PageIndex
	{
		get
		{
			return this.pageIndex;
		}
		private set
		{
			value = Mathf.Clamp(value, 0, this.PageCount - 1);
			if (this.pageIndex == value)
			{
				this.Invalidate();
				return;
			}
			this.pageIndex = value;
			if (!this.designInEditor)
			{
				this.UpdatePages();
			}
			this.Invalidate();
			if (this.pageIconAlign != PAGE_ICON_ALIGN.DISABLE)
			{
				this.UpdateIcons();
			}
			if (this.listener != null)
			{
				if (this.designInEditor)
				{
					this.listener.OnChangedPage(this, this.designPages[this.pageIndex], this.pageIndex);
				}
				else
				{
					this.listener.OnChangedPage(this, this.pages[1], this.pageIndex);
				}
			}
		}
	}

	public int PageCount
	{
		get
		{
			return this.pageCount;
		}
		set
		{
			if (this.pageCount == value)
			{
				return;
			}
			this.pageCount = value;
			if (this.pageCount > 1)
			{
				this.valuePerPage = 1f / (float)(this.pageCount - 1);
			}
			else
			{
				this.valuePerPage = 1f;
			}
			this.threshold = Mathf.Min(1f, this.valuePerPage * this.movementSensitivity);
			this.pageIndex = 0;
			this.UpdatePages();
			if (this.scroll != null)
			{
				this.scroll.Value = 0f;
				this.scroll.ContentLength = this.scroll.VisibleAreaLength * (float)this.pageCount;
			}
			if (this.pageIconAlign != PAGE_ICON_ALIGN.DISABLE)
			{
				this.UpdateIcons();
			}
		}
	}

	public float PageGap
	{
		get
		{
			return this.pageGap;
		}
		set
		{
			if (this.pageGap == value)
			{
				return;
			}
			this.pageGap = value;
			this.scroll.VisibleAreaLength = value;
			this.UpdatePages();
			if (this.scroll != null)
			{
				this.scroll.Value = 0f;
				this.scroll.ContentLength = this.scroll.VisibleAreaLength * (float)this.pageCount;
			}
		}
	}

	private void Awake()
	{
		this.scroll = base.GetComponent<tk2dUIScrollableArea>();
		this.boxCollider = base.GetComponent<BoxCollider>();
		if (this.scroll == null)
		{
			UnityEngine.Debug.LogWarning("Can't find 'tk2dUIScrollableArea' component.");
			return;
		}
		if (this.boxCollider == null)
		{
			UnityEngine.Debug.LogWarning("Can't find 'BoxCollider' component.");
			return;
		}
		if (this.pageCamera == null)
		{
			UnityEngine.Debug.LogWarning("'Page Camera' must be set.");
			return;
		}
		if (this.pageLengthIsScreen && this.pageCamera == null)
		{
			UnityEngine.Debug.LogWarning("Page Camera is null.");
			return;
		}
		if (this.eventListener != null)
		{
			if (this.useLevelPackage)
			{
				this.listener = (this.eventListener.GetComponent(typeof(IScrollLevel)) as IScrollPage);
				if (this.listener == null)
				{
					UnityEngine.Debug.LogWarning("Event Listener must inherit 'IScrollLevel'");
					return;
				}
			}
			else
			{
				this.listener = (this.eventListener.GetComponent(typeof(IScrollPage)) as IScrollPage);
			}
		}
		this.scroll.VisibleAreaLength = ((!this.pageLengthIsScreen) ? this.pageGap : this.pageCamera.ScreenExtents.width);
		if (this.designInEditor)
		{
			this.designPages = new List<GameObject>(this.customPages);
			this.PageCount = this.designPages.Count;
		}
		else
		{
			this.designPages = new List<GameObject>();
			this.CreatePage(this.preparePageCount);
		}
	}

	private void OnEnable()
	{
		if (this.scroll.backgroundUIItem != null)
		{
			this.scroll.backgroundUIItem.OnDown += this.OnButtonDown;
			this.scroll.backgroundUIItem.OnRelease += this.OnButtonRelease;
		}
	}

	private void OnDisable()
	{
		if (this.scroll.backgroundUIItem != null)
		{
			this.scroll.backgroundUIItem.OnDown -= this.OnButtonDown;
			this.scroll.backgroundUIItem.OnRelease -= this.OnButtonRelease;
		}
	}

	private void OnButtonDown()
	{
		if (this.PageCount <= 1)
		{
			return;
		}
		this.StopTween();
		this.downValue = this.scroll.Value;
		this.pressTime = Time.realtimeSinceStartup;
	}

	private void OnButtonRelease()
	{
		this.upValue = this.scroll.Value;
		this.ProcessPaging(0.5f);
	}

	public void Invalidate()
	{
		if (this.PageCount == 0)
		{
			return;
		}
		if (this.PageIndex >= this.PageCount)
		{
			UnityEngine.Debug.LogWarning("Wrong page index.");
			return;
		}
		if (this.designInEditor)
		{
			if (this.autoDeactivePage)
			{
				foreach (GameObject gameObject in this.designPages)
				{
					gameObject.SetActive(false);
				}
			}
			this.UpdatePage(this.designPages[this.PageIndex], this.PageIndex);
			if (this.PageIndex > 0)
			{
				this.UpdatePage(this.designPages[this.PageIndex - 1], this.PageIndex - 1);
			}
			if (this.PageIndex < this.PageCount - 1)
			{
				this.UpdatePage(this.designPages[this.PageIndex + 1], this.PageIndex + 1);
			}
		}
		else
		{
			this.UpdatePage(this.pages[1], this.PageIndex);
			if (this.PageIndex > 0)
			{
				this.UpdatePage(this.pages[0], this.PageIndex - 1);
			}
			if (this.PageIndex < this.PageCount - 1)
			{
				this.UpdatePage(this.pages[2], this.PageIndex + 1);
			}
		}
	}

	private void UpdatePage(GameObject page, int updatePageIndex)
	{
		page.SetActive(true);
		if (this.listener == null)
		{
			return;
		}
		this.listener.OnUpdatePage(this, page, updatePageIndex);
		if (this.designInEditor)
		{
			return;
		}
		if (!this.useLevelPackage)
		{
			return;
		}
		PackagePage component = page.GetComponent<PackagePage>();
		if (component == null)
		{
			return;
		}
		for (int i = 0; i < this.packageHeight; i++)
		{
			for (int j = 0; j < this.packageWidth; j++)
			{
				int num = this.packageWidth * i + j;
				int levelIndex = this.packageWidth * this.packageHeight * updatePageIndex + num;
				bool active;
				(this.listener as IScrollLevel).OnUpdateLevel(this, component[num], updatePageIndex, levelIndex, out active);
				component[num].SetActive(active);
			}
		}
	}

	public void ChangePage(int _pageIndex, bool withAnimation = false, float duration = 0.5f)
	{
		_pageIndex = Mathf.Clamp(_pageIndex, 0, this.PageCount - 1);
		if (_pageIndex == this.PageIndex)
		{
			this.Invalidate();
		}
		else
		{
			if (withAnimation)
			{
				this.GoTo(_pageIndex, duration);
			}
			else
			{
				this.StopTween();
				this.scroll.Value = this.valuePerPage * (float)_pageIndex;
			}
			this.PageIndex = _pageIndex;
		}
	}

	public void GoToNextPage()
	{
		this.ChangePage(this.PageIndex + 1, true, 0.5f);
	}

	public void GoToPrevPage()
	{
		this.ChangePage(this.PageIndex - 1, true, 0.5f);
	}

	private void GoTo(int targetIndex, float duration)
	{
		targetIndex = Mathf.Clamp(targetIndex, 0, this.PageCount - 1);
		if (targetIndex == this.PageIndex)
		{
			return;
		}
		this.TweenPage(duration, this.valuePerPage * (float)targetIndex);
	}

	private void ProcessPaging(float duration = 0.5f)
	{
		float num = this.upValue - this.downValue;
		float num2 = Mathf.Abs(num);
		float num3 = this.valuePerPage * (float)this.PageIndex;
		int num4 = this.PageIndex;
		float num5 = Time.realtimeSinceStartup - this.pressTime;
		if (num5 < this.accelerationThresholdTime)
		{
			float num6 = num / num5 * Time.deltaTime;
			float num7 = Mathf.Abs(num6);
			if (num7 > this.threshold * this.accelerationSensitivity * Time.deltaTime)
			{
				if (!this.pageLengthIsScreen)
				{
					num4 = Convert.ToInt32(Mathf.Max(0f, Mathf.Round(this.scroll.contentContainer.transform.localPosition.x / -this.pageGap)));
					if (this.PageIndex == num4)
					{
						if (num6 > 0f)
						{
							num4++;
						}
						else
						{
							num4--;
						}
					}
				}
				else if (num6 > 0f)
				{
					num4++;
				}
				else
				{
					num4--;
				}
				num4 = Mathf.Clamp(num4, 0, this.PageCount - 1);
			}
		}
		else if (num2 > this.threshold)
		{
			if (!this.pageLengthIsScreen)
			{
				num4 = Convert.ToInt32(Mathf.Max(0f, Mathf.Round(this.scroll.contentContainer.transform.localPosition.x / -this.pageGap)));
			}
			else if (num > 0f)
			{
				num4++;
			}
			else
			{
				num4--;
			}
			num4 = Mathf.Clamp(num4, 0, this.PageCount - 1);
		}
		if (num2 > 0f)
		{
			this.TweenPage(duration - duration * (num2 / this.valuePerPage), (float)num4 * this.valuePerPage);
			if (this.PageIndex != num4)
			{
				this.PageIndex = num4;
			}
		}
		else if (this.scroll.Value != num3)
		{
			float num8 = this.valuePerPage - Mathf.Abs(this.scroll.Value - num3);
			this.TweenPage(duration - duration * (num8 / this.valuePerPage), (float)num4 * this.valuePerPage);
		}
	}

	private void UpdatePages()
	{
		if (this.designInEditor)
		{
			if (this.designPages.Count < this.PageCount)
			{
				this.CreatePage(this.PageCount - this.designPages.Count);
			}
			for (int i = 0; i < this.designPages.Count; i++)
			{
				this.designPages[i].name = "Page" + i;
				this.designPages[i].transform.localPosition = Vector3.right * this.scroll.VisibleAreaLength * (float)i;
				this.designPages[i].SetActive(i < this.PageCount);
			}
		}
		else
		{
			for (int j = 0; j < this.pages.Length; j++)
			{
				int num = this.pageIndex - 1 + j;
				this.pages[j].name = "Page" + num;
				this.pages[j].transform.localPosition = Vector3.right * this.scroll.VisibleAreaLength * (float)num;
				this.pages[j].SetActive(num >= 0 && num < this.PageCount);
			}
		}
	}

	private void CreatePage(int count)
	{
		if (this.pagePrefab == null)
		{
			this.pagePrefab = new GameObject();
		}
		if (this.useLevelPackage)
		{
			PackagePage component = this.pagePrefab.GetComponent<PackagePage>();
			if (component == null)
			{
				this.pagePrefab.AddComponent<PackagePage>();
			}
		}
		if (this.designInEditor)
		{
			for (int i = 0; i < count; i++)
			{
				GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this.pagePrefab);
				gameObject.transform.parent = this.scroll.contentContainer.transform;
				if (this.useLevelPackage)
				{
					PackagePage component2 = gameObject.GetComponent<PackagePage>();
					component2.Reset(this);
				}
				this.designPages.Add(gameObject);
			}
		}
		else if (this.pages == null)
		{
			this.pages = new GameObject[3];
			for (int j = 0; j < 3; j++)
			{
				this.pages[j] = UnityEngine.Object.Instantiate<GameObject>(this.pagePrefab);
				this.pages[j].transform.parent = this.scroll.contentContainer.transform;
				if (this.useLevelPackage)
				{
					PackagePage component3 = this.pages[j].GetComponent<PackagePage>();
					component3.Reset(this);
				}
			}
		}
	}

	private void UpdateIcons()
	{
		if (this.iconsParent == null)
		{
			this.iconsParent = new GameObject("PageIcons");
			this.iconsParent.transform.parent = base.transform;
			float num = this.iconMargin;
			Renderer renderer = null;
			if (this.designPages.Count > 0 && this.designPages[this.PageIndex].GetComponent<Renderer>() != null)
			{
				renderer = this.designPages[this.PageIndex].GetComponent<Renderer>();
			}
			if (renderer == null)
			{
				if (this.useLevelPackage)
				{
					num += (this.levelSize.y * (float)this.packageHeight + this.packageMargin.y * (float)(this.packageHeight - 1)) * 0.5f;
				}
			}
			else
			{
				num += renderer.bounds.size.y * 0.5f;
			}
			if (this.pageIconAlign == PAGE_ICON_ALIGN.TOP)
			{
				this.iconsParent.transform.localPosition = Vector3.up * num;
			}
			else
			{
				this.iconsParent.transform.localPosition = Vector3.down * num;
			}
			this.activeIcon = UnityEngine.Object.Instantiate<GameObject>(this.activePageIcon);
			this.activeIcon.transform.parent = this.iconsParent.transform;
			this.activeIcon.transform.localScale = this.activePageIcon.transform.localScale;
			this.pageIcons.Add(this.activeIcon);
		}
		if (this.pageIcons.Count < this.PageCount)
		{
			int num2 = this.PageCount - this.pageIcons.Count;
			for (int i = 0; i < num2; i++)
			{
				GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this.deactivePageIcon);
				gameObject.transform.parent = this.iconsParent.transform;
				gameObject.transform.localScale = this.deactivePageIcon.transform.localScale;
				this.pageIcons.Add(gameObject);
			}
		}
		this.pageIcons.Remove(this.activeIcon);
		this.pageIcons.Insert(this.PageIndex, this.activeIcon);
		for (int j = 0; j < this.pageIcons.Count; j++)
		{
			this.pageIcons[j].SetActive(j < this.PageCount);
		}
		float num3 = this.iconOffset * (float)(this.PageCount - 1) * -0.5f;
		for (int k = 0; k < this.PageCount; k++)
		{
			this.pageIcons[k].transform.localPosition = new Vector3(num3 + (float)k * this.iconOffset, 0f, 0f);
		}
	}

	private void TweenPage(float duration, float destinationValue)
	{
		if (destinationValue != this.prevDestinationValue)
		{
			this.StopTween();
		}
		if (!this.IsTweening())
		{
			TweenParms tweenParms = new TweenParms().Prop("Value", destinationValue);
			tweenParms.Ease(EaseType.EaseOutQuad);
			tweenParms.OnComplete(delegate()
			{
				if (this.eventListener != null)
				{
					this.eventListener.SendMessage("OnCompleteSwipe", this.prevPageIndex, SendMessageOptions.DontRequireReceiver);
				}
				this.prevPageIndex = this.PageIndex;
			});
			this.tweener = HOTween.To(this.scroll, duration, tweenParms);
			this.prevDestinationValue = destinationValue;
		}
	}

	private void StopTween()
	{
		if (this.IsTweening())
		{
			this.tweener.Kill();
		}
	}

	private bool IsTweening()
	{
		return this.tweener != null && !this.tweener.destroyed;
	}

	[HideInInspector]
	[SerializeField]
	public float pageGap;

	[HideInInspector]
	[SerializeField]
	public float iconOffset = 0.5f;

	[HideInInspector]
	[SerializeField]
	public float iconMargin = 1f;

	[HideInInspector]
	[SerializeField]
	public int packageWidth = 5;

	[HideInInspector]
	[SerializeField]
	public int packageHeight = 5;

	[HideInInspector]
	[SerializeField]
	public bool designInEditor = true;

	[HideInInspector]
	[SerializeField]
	public bool useLevelPackage;

	[HideInInspector]
	[SerializeField]
	public int preparePageCount;

	[HideInInspector]
	[SerializeField]
	public bool autoDeactivePage = true;

	[HideInInspector]
	[SerializeField]
	public tk2dCamera pageCamera;

	[HideInInspector]
	[SerializeField]
	public Vector2 packageMargin;

	[HideInInspector]
	[SerializeField]
	public Vector2 packageOffset;

	[HideInInspector]
	[SerializeField]
	public GameObject pagePrefab;

	[HideInInspector]
	[SerializeField]
	public GameObject levelPrefab;

	[HideInInspector]
	[SerializeField]
	public Vector2 levelSize;

	[HideInInspector]
	[SerializeField]
	public GameObject eventListener;

	[HideInInspector]
	[SerializeField]
	public GameObject[] customPages;

	[HideInInspector]
	[SerializeField]
	public GameObject activePageIcon;

	[HideInInspector]
	[SerializeField]
	public GameObject deactivePageIcon;

	[HideInInspector]
	[SerializeField]
	public PAGE_ICON_ALIGN pageIconAlign;

	[HideInInspector]
	[SerializeField]
	public bool pageLengthIsScreen = true;

	[HideInInspector]
	[SerializeField]
	public float movementSensitivity = 0.2f;

	[HideInInspector]
	[SerializeField]
	public float accelerationThresholdTime = 0.3f;

	[HideInInspector]
	[SerializeField]
	public float accelerationSensitivity = 0.5f;

	[HideInInspector]
	[SerializeField]
	public string eventMessageName = string.Empty;

	private int pageIndex;

	private int pageCount;

	private int prevPageIndex;

	private bool isDragging;

	private bool initialized;

	private float valuePerPage;

	private float threshold;

	private float downValue;

	private float upValue;

	private float pressTime;

	private float prevDestinationValue;

	private Tweener tweener;

	private GameObject activeIcon;

	private GameObject iconsParent;

	private IScrollPage listener;

	private BoxCollider boxCollider;

	private tk2dUIScrollableArea scroll;

	private GameObject[] pages;

	private List<GameObject> designPages;

	private List<GameObject> pageIcons = new List<GameObject>();
}
